package com.intretech.tj.gpp

import com.intretech.tj.gpp.entity.DO.Edge
import com.intretech.tj.gpp.entity.DO.RfidNode
import com.intretech.tj.gpp.entity.DTO.light.LightStatus
import jakarta.enterprise.context.ApplicationScoped
import java.util.Collections.emptyList
import java.util.concurrent.ConcurrentHashMap

@ApplicationScoped
open class Graph {
    // 使用 ConcurrentHashMap 保证线程安全
    // 边集
    open val nodes = ConcurrentHashMap<Int, RfidNode>()

    // 点集
    open val edges = ConcurrentHashMap<Int, Edge>()

    // 图
    private val adjacencyList = ConcurrentHashMap<Int, MutableList<Edge>>()

    // 禁用边
    private val disabledEdges = ConcurrentHashMap.newKeySet<Int>()

    // 灯的状态
    private val trafficLights = ConcurrentHashMap<Int, LightStatus>()

    // 新增: 用于跟踪车辆在“节点”上的位置
    val vehicleAtNodeMap = ConcurrentHashMap<String, Int>() // vehicleId -> nodeId

    // 用于跟踪车辆在“边”上的位置
    private val vehicleToEdgeMap = ConcurrentHashMap<String, Int>()  // vehicleId -> edgeId

    // 返回地图数据
    fun getEdgesAndNodes(): Pair<List<RfidNode>, List<Edge>> {
        val edgesList = edges.values.toList()
        val nodesList = nodes.values.toList()
        return nodesList to edgesList
    }

    // 车辆开始进入一条边
    fun placeVehicleOnEdge(vehicleId: String, edgeId: Int) {
        // 从可能停泊的节点上移除
        vehicleAtNodeMap.remove(vehicleId)
        // 放置到边上
        vehicleToEdgeMap[vehicleId] = edgeId
    }

    // 车辆到达节点并停泊
    fun parkVehicleAtNode(vehicleId: String, nodeId: Int) {
        // 从可能行驶的边上移除
        vehicleToEdgeMap.remove(vehicleId)
        // 放置到节点上
        vehicleAtNodeMap[vehicleId] = nodeId
    }

    // 彻底移除车辆（用于下线清理）
    fun removeVehicle(vehicleId: String) {
        vehicleToEdgeMap.remove(vehicleId)
        vehicleAtNodeMap.remove(vehicleId)
    }

    // 新增: 获取停在某个节点上的车辆数
    fun getVehiclesAtNode(nodeId: Int): Int {
        return vehicleAtNodeMap.values.count { it == nodeId }
    }

    fun getEdge(edgeId: Int): Edge? {
        return edges[edgeId]
    }

    // 寻找从 startNodeId 到 endNodeId 的边
    fun findEdgeBetween(startNodeId: Int, endNodeId: Int): Edge? {
        return adjacencyList[startNodeId]?.find { it.rfidNodeEnd == endNodeId }
    }

    fun removeVehicleLocation(vehicleId: String) {
        vehicleToEdgeMap.remove(vehicleId)
    }

    /**
     * 统计指定边上有多少车辆。
     * @param edgeId          边的 ID
     * @param vehicleId  （可选）要排除的车辆 ID，如果为 null 则不过滤
     * @return 车辆数量
     */
    fun getVehiclesOnEdge(edgeId: Int, vehicleId: String? = null): Int {
        return vehicleToEdgeMap
            // 只保留在这条边上的条目
            .filter { it.value == edgeId }
            // 如果传了 excludeVehicle，就把自己排除掉
            .filter { vehicleId == null || it.key != vehicleId }
            .size
    }


    fun addNode(node: RfidNode) {
        nodes[node.id] = node
        adjacencyList.putIfAbsent(node.id, mutableListOf())
    }

    fun addEdge(edge: Edge) {
        edges[edge.id] = edge
        adjacencyList.computeIfAbsent(edge.rfidNodeStart) { mutableListOf() }.add(edge)
    }

    fun disableEdge(edgeId: Int) {
        disabledEdges.add(edgeId)
    }

    fun enableEdge(edgeId: Int) {
        disabledEdges.remove(edgeId)
    }

    fun updateTrafficLight(lightId: Int, status: LightStatus) {
        trafficLights[lightId] = status
    }


    fun getEdgesFrom(nodeId: Int): List<Edge> {
        return adjacencyList[nodeId] ?: emptyList()
    }


    fun getNode(nodeId: Int): RfidNode? {
        return nodes[nodeId]
    }

    fun isEdgeDisabled(edgeId: Int): Boolean {
        return disabledEdges.contains(edgeId)
    }

    fun getTrafficLightStatus(nodeId: Int): LightStatus? {
        val node = nodes[nodeId]
        return node?.lightId?.let { trafficLights[it] }
    }

    fun clear() {
        nodes.clear()
        edges.clear()
        adjacencyList.clear()
        disabledEdges.clear()
        trafficLights.clear()
    }


}